"""
组合调仓策略示例
测试adjust_target_position功能
"""
import os
import sys
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_root)
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
from loguru import logger

from engine.engine import BacktestEngine
from engine.assets import Bond
from engine.event import AssetType  # 添加AssetType导入
from strategy.base import Strategy
from visualization.performance import PerformanceAnalyzer, PerformanceVisualizer

class PortfolioRebalanceStrategy(Strategy):
    """
    组合调仓策略
    每隔一定时间，根据债券到期收益率进行调仓
    选择到期收益率最高的N只债券，平均分配仓位
    """
    
    def __init__(self,
                 name: str = "债券组合调仓策略",
                 initial_capital: float = 1000000.0,
                 risk_limit: float = 0.2,
                 rebalance_days: int = 20,  # 调仓周期（交易日）
                 top_n: int = 3):  # 选择收益率最高的前N只债券
        """
        初始化策略
        
        Args:
            name: 策略名称
            initial_capital: 初始资金
            risk_limit: 风险限额
            rebalance_days: 调仓周期（交易日）
            top_n: 选择收益率最高的前N只债券
        """
        super().__init__(name=name,
                        initial_capital=initial_capital,
                        risk_limit=risk_limit)
        self.rebalance_days = rebalance_days
        self.top_n = top_n
        self.last_rebalance_date = None
        
    def initialize(self) -> None:
        """策略初始化"""
        logger.info("初始化债券组合调仓策略")
        self.last_rebalance_date = None
        
    def on_data(self, data) -> None:
        """
        数据更新事件
        检查是否需要调仓，如果需要则获取当前所有债券的到期收益率，
        选择收益率最高的N只债券平均分配仓位
        """
        self.current_date = self.engine.current_time
        # 检查是否需要调仓
        if self.last_rebalance_date is None:
            need_rebalance = True
        else:
            days_passed = len(self.market_data[list(self.market_data.keys())[0]].loc[
                self.last_rebalance_date:self.current_date
            ]) - 1
            need_rebalance = days_passed >= self.rebalance_days
            
        if not need_rebalance:
            return
            
        # 获取所有债券的到期收益率
        ytm_dict = {}
        for symbol, asset in self.available_assets.items():
            if isinstance(asset, Bond):
                try:
                    ytm = asset.calc_ytm(
                        clean_price=self.get_current_price(symbol),
                        value_date=self.current_date
                    )

                    ytm_dict[symbol] = ytm
                except Exception as e:
                    logger.warning(f"计算{symbol}的到期收益率失败: {e}")
                    continue
        
        if not ytm_dict:
            logger.warning("没有可用的债券收益率数据")
            return
            
        # 选择收益率最高的N只债券
        top_bonds = sorted(ytm_dict.items(), key=lambda x: x[1], reverse=True)[:self.top_n]
        
        # 计算目标持仓
        weight = self.leverage / len(top_bonds)  # 平均分配仓位
        target_positions = {symbol: weight for symbol, _ in top_bonds}
        
        # 调整仓位
        self.adjust_target_position(target_positions)
        
        # 更新最后调仓日期
        self.last_rebalance_date = self.current_date
        
        # 输出调仓信息
        logger.info(f"调仓日期: {self.current_date}")
        for symbol, ytm in top_bonds:
            logger.info(f"债券{symbol} YTM: {ytm:.2%}")

def main():
    # 创建回测引擎
    engine = BacktestEngine(commission_rate=0.00,slippage_rate=0.00)
    
    # 创建策略实例
    strategy = PortfolioRebalanceStrategy(
        name="债券组合调仓策略",
        initial_capital=1000000.0,
        risk_limit=0.2,
        rebalance_days=20,  # 20个交易日调仓一次
        top_n=3  # 选择收益率最高的3只债券
    )
    print(1)
    # 创建债券
    bonds = [
        Bond(
            symbol=f"bond_{i}",
            asset_type=AssetType.BOND,  # 添加asset_type参数
            par_value=100.0,  # 使用正确的参数名par_value
            coupon_rate=0.03 + i * 0.0001,  # 3% - 5%的票面利率
            value_date=datetime(2024, 1, 1),
            maturity_date=datetime(2025, 1, 1),
            payment_frequency=2
        )
        for i in range(10)  # 创建10只债券
    ]
    
    # 生成模拟价格数据
    start_date = datetime(2024, 1, 1)
    end_date = datetime(2024, 6, 30)
    dates = pd.date_range(start=start_date, end=end_date, freq='B')
    
    for bond in bonds:
        i = np.random.randint(1,123)
        # 生成随机价格序列，围绕面值波动
        np.random.seed(4222*i)  # 设置随机种子，保证可重复性
        prices = 100 + np.random.normal(0, 2, size=len(dates))  # 均值100，标准差2
        
        # 创建价格数据DataFrame
        price_data = pd.DataFrame({
            'open': prices,
            'high': prices + 0.1,
            'low': prices - 0.1,
            'close': prices,
            'volume': 1000000
        }, index=dates)
        
        # 添加数据到策略和引擎中

        engine.add_market_data(bond.symbol, price_data)
        engine.add_asset(bond)
    
    # 设置回测参数
    engine.set_strategy(strategy)
    
    # 运行回测
    results = engine.run_backtest()
    print(results)
    
    # 创建性能分析器和可视化器
    analyzer = PerformanceAnalyzer(results)
    visualizer = PerformanceVisualizer(analyzer)
    
    # 生成HTML报告
    visualizer.export_html_report('backtest_report.html')
    
    # 输出回测结果
    print("\n=== 回测结果 ===")
    metrics = engine.get_performance_metrics()
    print("回测完成!")
    print("指标:", metrics)

if __name__ == "__main__":
    main()
